#include "vg/simple_shape.h"

using namespace anip;

class vg::SimpleShape::Renderer : public GraphicsRenderer
{
private:
	SimpleShape& _shape;

public:
	Renderer(SimpleShape& s) :
		_shape(s)
	{
		_version = s.version();
	}

	GraphicObject& graphicObject() const override { return _shape; }
	void render(GraphicsRenderContext& cxt) override;
};

void vg::SimpleShape::Renderer::render(GraphicsRenderContext& cxt)
{
	vec2 pos = _shape.position[_currentFrame];
	vec2 size = _shape.size[_currentFrame];
	anip::color col = _shape.color[_currentFrame];
	switch (_shape.type)
	{
	case Type::Square:
		Draw::rect(pos, size, col);
		break;
	case Type::Ellipse:
		Draw::ellipse(pos, size, col);
		break;
	case Type::RoundedSquare:
		float rad = _shape.parameter[_currentFrame];
		Draw::roundedRect(pos, size, rad, col);
		break;
	}
}

bool vg::SimpleShape::isInside(invec2 p, float time)
{
	vec2 pos = position[time];
	vec2 sz = size[time];
	vec2 vp = (p - pos) / sz;
	switch (type)
	{
	case Type::Square:
		return vp.x > 0 && vp.y > 0 && vp.x < 1 && vp.y < 1;
	case Type::Ellipse:
		return math::length(vp - vec2{ 0.5f, 0.5f }) < 0.5;
	case Type::RoundedSquare:
		// ANIP_FIXME make this more precise?
		return vp.x > 0 && vp.y > 0 && vp.x < 1 && vp.y < 1;
	}
	return false;
}

GraphicsRenderer* anip::vg::SimpleShape::createRenderer()
{
	return new Renderer(*this);
}

serializer_implementation(vg::SimpleShape)(Primitive& obj, std::ostream& out)
{
	auto& s = (SimpleShape&)obj;
	binaryWrite(s.position, out);
	binaryWrite(s.size, out);
	binaryWrite(s.color, out);
	binaryWrite(s.parameter, out);
	binaryWrite(s.type, out);
}

deserializer_implementation(vg::SimpleShape)(std::istream& in)
{
	auto s = new SimpleShape();
	binaryRead(s->position, in);
	binaryRead(s->size, in);
	binaryRead(s->color, in);
	binaryRead(s->parameter, in);
	binaryRead(s->type, in);
	return s;
}